using System;
using System.Runtime.Serialization;
using System.Xml;
using SharpObjects.Configuration;
using SharpObjects.Configuration.ConfigurationProviders;
using SharpObjects.Instantiation.Services;
using SharpObjects.Interfaces;

namespace SharpObjects.Configuration.Services
{
    [Serializable]
    [DataContract]
    public class ConfigurableServiceDescriptor : ServiceDescriptor, IXmlInitializable
    {
        public XmlElement ServiceInitializationElement { get; set; }

        public ConfigurableServiceDescriptor()
        {
        }

        public ConfigurableServiceDescriptor(ITypeDescriptor typeDescriptor = null)
            : base(typeDescriptor)
        {
        }

        public void Initialize(XmlElement initializationElement)
        {
            IConfigurationProvider init = new XmlConfigurationProvider(initializationElement);

            this.ServiceId = init.GetString("@name", init.GetString("@id"));
            this.ServiceVersion = init.GetString("@version", null);
            this.IsSingleton = init.GetBoolean("@is_singleton", false);

            this.PreInstantiate = init.GetBoolean("pre_instantiate", init.GetBoolean("@pre_instantiate", false));
            this.PreInstantiateVersions = init.GetStrings("pre_instantiate_version");

            if(initializationElement.SelectSingleNode("type_descriptor") != null)
            {
                this.TypeDescriptor = init.GetObject<ITypeDescriptor>("type_descriptor");
            }
            else
            {
                this.TypeDescriptor = new ConfigurableTypeDescriptor();
                ((ConfigurableTypeDescriptor)this.TypeDescriptor).Initialize(initializationElement);
            }

            this.ServiceInitializationElement = initializationElement;

            this.IsInitialized = true;
        }

        public bool IsInitialized { get; set; }


        public override IServiceDescriptor Clone()
        {
            ConfigurableServiceDescriptor configurableServiceDescriptor = new ConfigurableServiceDescriptor()
                                                                              {
                                                                                  ServiceId = this.ServiceId,
                                                                                  ServiceVersion = this.ServiceVersion,
                                                                                  TypeDescriptor = this.TypeDescriptor,
                                                                                  PreInstantiate = this.PreInstantiate,
                                                                                  PreInstantiateVersions = this.PreInstantiateVersions,
                                                                                  IsSingleton = this.IsSingleton,
                                                                                  SingletonInstance = null
                                                                              };

            configurableServiceDescriptor.ServiceInitializationElement = this.ServiceInitializationElement;

            return (IServiceDescriptor) configurableServiceDescriptor;
        }
    }
}